import React, {useCallback, useEffect, useMemo, useState} from 'react';
import {Button, Select, Spin} from 'antd';
import {debounce} from 'lodash';

// 选项类型定义
interface OptionType {
    [labelKey: string]: React.ReactNode;

    [valueKey: string]: string | number;
}

// 组件属性定义
interface AsyncSelectProps {
    // 异步获取选项的函数
    fetchOptions: (params: { current: number; pageSize: number; code?: string; }) => Promise<{ record: OptionType[]; total: number }>;

    // 选项的标签字段名
    labelKey?: string;

    // 选项的值字段名
    valueKey?: string;

    // 当前选中值
    value?: string | number | string[] | number[];

    // 值变化时的回调
    onChange?: (value: any) => void;

    // 选择单个选项时的回调
    onSelect?: (value: string | number, option: OptionType) => void;

    // 多选模式
    mode?: 'multiple' | 'tags';

    // 占位符文本
    placeholder?: string;

    // 每页显示数量
    pageSize: number;

    // 搜索防抖时间(ms)
    debounceTime?: number;

    // 是否禁用组件
    disabled?: boolean;

    // 其他Select组件支持的属性
    [key: string]: any;
}

const AsyncSelect: React.FC<AsyncSelectProps> = ({
                                                     fetchOptions,
                                                     labelKey = 'label',
                                                     valueKey = 'value',
                                                     value,
                                                     onChange,
                                                     onSelect,
                                                     mode,
                                                     placeholder = '请选择...',
                                                     pageSize = 50,
                                                     debounceTime = 300,
                                                     disabled = false,
                                                     ...rest
                                                 }) => {
    // 当前加载的选项
    const [options, setOptions] = useState<OptionType[]>([]);

    // 总选项数量
    const [total, setTotal] = useState(0);

    // 当前页码
    const [currentPage, setCurrentPage] = useState(1);

    // 搜索关键词
    const [keyword, setKeyword] = useState('');

    // 加载状态
    const [loading, setLoading] = useState(false);

    // 是否还有更多数据
    const hasMore = useMemo(() => options.length < total, [options.length, total]);

    // 格式化选项数据
    const formattedOptions = useMemo(() => {
        return options.map(option => ({
            label: option[labelKey],
            value: option[valueKey],
            ...option,
        }));
    }, [options, labelKey, valueKey]);

    // 处理滚动加载更多
    const handleScroll = useCallback((e: React.UIEvent<HTMLDivElement>) => {
        const {scrollTop, scrollHeight, clientHeight} = e.currentTarget;

        // 滚动到底部时加载更多
        if (scrollTop + clientHeight >= scrollHeight - 50 && hasMore && !loading) {
            loadMore();
        }
    }, [hasMore, loading]);

    // 加载更多选项
    const loadMore = useCallback(async () => {
        if (!hasMore || loading) return;

        setLoading(true);
        try {
            const nextPage = currentPage + 1;
            const res = await fetchOptions({
                current: nextPage,
                pageSize,
                code: keyword,
            });
            console.log('res', res)
            setOptions(prev => [...prev, ...res.record]);
            setCurrentPage(nextPage);
            setTotal(res.total);
        } catch (error) {
            console.error('加载更多选项失败:', error);
        } finally {
            setLoading(false);
        }
    }, [currentPage, keyword, pageSize, hasMore, loading, fetchOptions]);

    // 搜索选项
    const handleSearch = useCallback(debounce(
        async (searchValue: string) => {
            setKeyword(searchValue);
            setCurrentPage(1);
            setLoading(true);

            try {
                const result = await fetchOptions({
                    code: searchValue,
                    current: 1,
                    pageSize,
                });
                // console.log('result', result)
                // console.log('options', result.record)
                setOptions(result.record);
                setTotal(result.total);
            } catch (error) {
                console.error('搜索选项失败:', error);
            } finally {
                setLoading(false);
            }
        },
        debounceTime
    ) as Function, [debounceTime, pageSize, fetchOptions]);

    // 处理值变化
    const handleChange = useCallback((newValue: any) => {
        onChange?.(newValue);
    }, [onChange]);

    // 处理选项选择
    const handleSelect = useCallback((value: string | number, option) => {
        onSelect?.(value, option as unknown as OptionType);
    }, [onSelect]);

    // 下拉框显示时加载第一页数据
    const handleDropdownVisibleChange = useCallback(async (visible: boolean) => {
        if (visible && options.length === 0) {
            await handleSearch('');
        }
    }, [options.length, handleSearch]);

    // 组件挂载时初始化
    useEffect(() => {
        if (!fetchOptions) {
            console.warn('未提供fetchOptions函数');
        }
    }, [fetchOptions]);

    return (
        <Select
            showSearch
            mode={mode}
            placeholder={placeholder}
            filterOption={false}
            loading={loading}
            value={value}
            onChange={handleChange}
            onSelect={handleSelect}
            onSearch={handleSearch}
            onDropdownVisibleChange={handleDropdownVisibleChange}
            disabled={disabled}
            dropdownRender={(menu) => (
                <>
                    {menu}
                    {hasMore && (
                        <div className="ant-select-dropdown-loading-more" style={{padding: 8, textAlign: 'center'}}>
                            {loading ? (
                                <Spin size="small"/>
                            ) : (
                                <Button
                                    onClick={loadMore}
                                >
                                    加载更多
                                </Button>
                            )}
                        </div>
                    )}
                </>
            )}
            onDropdownScroll={handleScroll}
            {...rest}
        >
            {formattedOptions.map(option => (
                <Select.Option key={option.value} value={option.value}>
                    {option.label}
                </Select.Option>
            ))}
        </Select>
    );
};

export default AsyncSelect;